package uform.ui.assembler;
import thx.collections.Set;
import uform.ui.comp.Form;
import uform.ui.comp.Component;
import thx.error.AbstractMethod;
import uform.model.core.IValueHandler;
import uform.ui.comp.Control;
import thx.validation.OptionValidator;
import thx.validation.Option;
import uform.model.value.ValueType;
import uform.ui.comp.SelectControl;
using Types;

class BaseAssembler<T : IValueHandler<Dynamic>> implements IComponentAssembler<T>
{
	public var form : Form;
	public var root : Assembler;
	public function new(root : Assembler) this.root = root
	public function assemble(type : T) : Component
	{
		return throw new AbstractMethod();
	}

	function _bindControlToModel(control : Control<Dynamic>) {
		var model = this.form.model;
//		control.enabled;
//		control.visible;
		
		control.value.onChange.add(function() {
			var path = control.path();
			var value = control.value.get();
			if(model.clearing)
			{
				model.set(path, null);
			} else {
				var old = model.get(path);
				if (old == value)
					return;
				switch(	model.validateAt(path, value))
				{
					case Ok:
						control.errors.reset();
					    model.set(path, value);
					case Failure(e):
						control.errors.set(e);
				}
			}
		});
	}

	function _bindModelToControl(control : Control<Dynamic>) {
		form.model.onChange.add(function(e) {
			if(e.path != control.path())
				return;
			control.value.set(e.value);
		});
	}

	function _bindBidirectional(control : Control<Dynamic>) {
		_bindModelToControl(control);
		_bindControlToModel(control);
	}
	
	function _options(type : T) : Component
	{
		if (!Std.is(type, ValueType))
			return null;
		var t : ValueType<Dynamic> = cast type;
		for (validator in t.validators)
		{
			var v = validator.as(OptionValidator);
			if (null == v)
				continue;
			return _optionsControl(t, v.options);
		}
		return null;
	}
	
	function _optionsControl(type : ValueType<Dynamic>, options : Array<Option<Dynamic>>)
	{
		var control = new SelectControl("");
		
		for(option in options)
			control.addOption(option);

		if (type.meta.exists("image"))
			control.imagePath.set(type.meta.get("image"));
			
		if (type.meta.exists("label-translation"))
			control.labelTranslation.set(type.meta.get("label-translation") == true);
		_bindBidirectional(control);
		return control;
	}
}